import json
from errors import RequestParamsError

JSON, ARGS = "json", "args"
ARG, DEST, REQUIRED, TYPE, DEFAULT = "arg", "dest", "required", "type", "default"


def parse_one(args: dict, rule: dict):
    """解析单个规则

    Args:
        args (dict): request中的参数
        rule (dict): 规则参数

    Raises:
        ValueError: arg值未设置
        RequestParamsError: 应传值在请求时未传
        ValueError: type值设置错误

    Returns:
        tuple: 解析后的key,value
    """
    if not rule.get(ARG):
        raise ValueError("arg值必传")
    key = rule[ARG]
    value = args.get(key)
    if rule.get(REQUIRED) and value is None:
        raise RequestParamsError("%s值未传值" % key)
    if value is None:
        if rule.get(DEFAULT) is not None:
            value = rule[DEFAULT]
        else:
            return key, None
    if rule.get(TYPE):
        if rule[TYPE] == "str":
            value = str(value[0]) if isinstance(value, list) else str(value)
        elif rule[TYPE] == "int":
            value = int(value[0]) if isinstance(value, list) else int(value)
        elif rule[TYPE] == "list":
            value = value if isinstance(value, list) else [value]
        elif rule[TYPE] == "dict":
            value = json.loads(value) if isinstance(value, str) else dict(value)
        else:
            raise ValueError("type值设置错误")
    if rule.get(DEST):
        key = rule[DEST]
    return key, value


def parse_args(request, location: str, rules: list) -> dict:
    """解析请求参数

    Args:
        request (sanic.request): sanic的请求
        location (str): 数据来源args或json
        rules (list): 解析规则

    Raises:
        ValueError: 规则错误

    Returns:
        dict: 解析后的参数
    """
    assert isinstance(rules, list)
    args, res = dict(), dict()
    if location == JSON:
        args = request.json
    elif location == ARGS:
        args = request.args
    else:
        raise ValueError("location错误")
    for rule in rules:
        k, v = parse_one(args, rule)
        if v is not None:
            res[k] = v
    return res
